feat(aztec-nr): wire constrained message delivery#23866
Conversation
b9f12b8 to
befb4ea
Compare
69abd69 to
e2a43cd
Compare
) Fixes [F-697](https://linear.app/aztec-labs/issue/F-697/aztec-nr-extend-the-onchaindelivery-builder-for-secret-origin) Fixes [F-649](https://linear.app/aztec-labs/issue/F-649/fixaztec-nr-skip-note-log-linkage-for-onchain-constrained-delivery-to) ## Summary - Extends `MessageDelivery` with separate typed builders for unconstrained and constrained on-chain delivery. - Adds internal tag-secret derivation config: - offchain: none - onchain unconstrained: address-pair by default, with optional non-interactive handshake selection - onchain constrained: non-interactive handshake - Introduces `OnchainDeliveryMode` as the typed on-chain mode used by tagging-index helpers and the HandshakeRegistry ABI instead of raw `u8` values. - Keeps invalid delivery/tag-derivation combinations rejected at compile time where possible. - Stops linking constrained-tagged note logs to note-hash squashing, so removing a squashed note does not break the recipient tag index chain. - Re-pins the HandshakeRegistry standard contract and updates the generated standard-contract metadata. Constrained tagging is still not fully wired up: the delivery config is validated, but tag emission remains mocked through the existing wallet-derived unconstrained path behind TODO(#14565). Stack: #23875, then this PR, then #23866, then #23867. --------- Co-authored-by: AztecBot <tech@aztec-labs.com> Co-authored-by: Nicolas Chamo <nicolas@chamo.com.ar>
6337393 to
c552943
Compare
…et_and_index Also corrects the safety comment on the registry utility call: a duplicate handshake replaces the stored note rather than failing, so the actual argument is that every branch constrains the secret it returns.
StatefulTest is a generic test contract used across e2e/PXE unit tests that don't exercise constrained-delivery semantics. Routing its `create_note`/`create_note_no_init_check`/`destroy_and_create_no_init_check` inserts through `onchain_constrained()` ties those tests to the constrained-msg nullifier chain — that breaks parallel-deploy block tests (chain collision on shared recipient), PXE unit tests that don't set up handshake state, and the e2e_2_pxes "no account secret key" scenario. Dedicated constrained-delivery coverage lives in ConstrainedDeliveryTest + e2e_constrained_delivery; same precedent as the earlier state_vars test switch.
7b401f0 to
7628eab
Compare
| const deployedContract = await deployContract(); | ||
|
|
||
| const sender = owner; | ||
| const insertConstrainedSelector = await deployedContract.methods.insert_note_constrained.selector(); |
There was a problem hiding this comment.
Just highlighting this is specifically a constrained note log test
nchamo
left a comment
There was a problem hiding this comment.
I'm still going over it, but wanted to share some initial feedback
| return ( | ||
| functionSelector.equals(await STANDARD_HANDSHAKE_REGISTRY_GET_APP_SILOED_SECRET_SELECTOR) && | ||
| args.length >= 4 && | ||
| // TODO(F-671): will be replaced with `self.msg_sender()` once utility context exposes it. |
There was a problem hiding this comment.
While it does make sense to have this, since we already have a PR in place (#24062), I would avoid it, simply to avoid merging conflicts
There was a problem hiding this comment.
I would avoid it, simply to avoid merging conflicts
Just for clarity sake, you mean this entire check right?
| /// The fields are private and there is no public constructor: a `MessageDelivery` can only be produced by a | ||
| /// [`MessageDeliveryBuilder`] that enforces valid configurations, so invalid field combinations cannot be | ||
| /// represented to the consumer. | ||
| /// [`MessageDeliveryBuilder`]. The delivery APIs validate the built configuration before consuming it. |
There was a problem hiding this comment.
I know that we are currently allowing to create "invalid" states, but that is only temporary (for a few PRs), right? The end state will only allow devs to build valid states, right?
There was a problem hiding this comment.
Yes that will be the end state.
| ) | ||
| } | ||
|
|
||
| mod test { |
There was a problem hiding this comment.
Is it me, or are we missing quite a lot of tests here?
I think we have a lot of behaviors and decision trees on this file that we are not testing. Could we?
There was a problem hiding this comment.
Most of the coverage is contained in constrained_delivery_test_contract/src/test.nr but yeah this could do with some unit tests.
There was a problem hiding this comment.
Added some unit tests
…src/main.nr Co-authored-by: Nicolas Chamo <nicolas@chamo.com.ar>
…_variables.md Co-authored-by: Nicolas Chamo <nicolas@chamo.com.ar>
…ule, handshake reg selector override constants
…lpers' into mv/f-669-constrained-delivery-helpers
Flakey Tests🤖 says: This CI run detected 1 tests that failed, but were tolerated due to a .test_patterns.yml entry. |
Fixes F-669
Fixes F-670
The change
0against the standard HandshakeRegistry, and constrainindex > 0through the previous chain nullifier.(secret, index)pair and emit the current constrained-message nullifier.Large portion of the diff is tests.
F-741 follow-up for the test skipped in fd07996.
Concurrency / batching constraint (worth a look)
Pinning the e2e tests surfaced a sequencing constraint in constrained delivery that reviewers should sanity-check:
(sender, recipient, secret)chain collide. Each send is keyed on an incrementing index, so two sends fired as separate parallel txs read the same index and one tx is rejected. Distinct recipients are distinct chains and parallelize fine. Pinned asit.failing(documents the limit; flips green if parallel sends ever become supported).emit_two_events) and client-sideBatchCall.get_or_create_app_siloed_handshake_secretis a utility call reading committed state, so a bootstrap earlier in the same tx is invisible and the later send mints a fresh secret on a separate chain (next index lands at 1, not 2). A new recipient therefore needs one landed tx to establish the chain before sends can be batched onto it. This is why the batched tests seed the handshake first.All four behaviors are pinned in
e2e_constrained_delivery.test.ts; the rationale lives in the module doc and onget_or_create_app_siloed_handshake_secret. Follow-up: allowing utility functions to execute against combined committed + pending transaction state is tracked in F-238.